package com.knight.server;

import com.knight.model.Order;
import com.knight.request.RPCRequest;
import com.knight.service.impl.OrderServiceImpl;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

public class Processor extends Thread {

    private InputStream inputStream;
    private OutputStream outputStream;
    private Map<String, Object> handlers;

    public Processor(Map<String, Object> handlers, InputStream inputStream, OutputStream outputStream) {
        this.inputStream = inputStream;
        this.outputStream = outputStream;
        this.handlers = handlers;
    }


    @Override
    public void run() {
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            objectInputStream = new ObjectInputStream(inputStream);
            objectOutputStream = new ObjectOutputStream(outputStream);

            RPCRequest request = (RPCRequest) objectInputStream.readObject();
            System.out.println(request);

            objectOutputStream.writeObject(invoke(request));
            objectOutputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } finally {
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    private Object invoke(RPCRequest request) throws ClassNotFoundException, NoSuchMethodException,
            InvocationTargetException, IllegalAccessException {
        String className = request.getClassName();
        String methodName = request.getMethodName();
        Object[] parameters = request.getParameters();
        Class<?>[] parametersTypes = null;
        if (parameters != null) {
            parametersTypes = new Class[parameters.length];
            for (int i = 0; i < parameters.length; i++) {
                parametersTypes[i] = parameters[i].getClass();
            }
        }
        Class<?> serviceImpl = Class.forName(className);
        Object service = handlers.get(className);
        if (service == null) {
            throw new RuntimeException("service not found:" + className);
        }
        Method serviceImplMethod = serviceImpl.getMethod(methodName, parametersTypes);
        return serviceImplMethod.invoke(service, parameters);
    }
}
